﻿#region Using

using System.Collections.Generic;
using System.Linq;

using GameCommon.Args;
using GameCommon.ManagerInterfaces;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

#endregion

namespace GameCommon.Manager
{
    internal class KeyboardManager : IKeyboardManager
    {
        private List<Keys> previousKeys;

        public KeyboardManager()
        {
            this.previousKeys = new List<Keys>();
        }

        public event KeyboardEventHandler KeyPressed;

        public event KeyboardEventHandler KeyReleased;

        public void Update(GameTime gameTime)
        {
            var keyboardState = Keyboard.GetState();
            var keys = keyboardState.GetPressedKeys().ToList();

            var modifiers = keys.Where(x => x == Keys.LeftShift || x == Keys.RightShift || x == Keys.LeftAlt || x == Keys.RightAlt || x == Keys.LeftControl || x == Keys.RightControl);

            var pressedKeys = keys.ToList();
            pressedKeys.RemoveAll(this.previousKeys.Contains);

            foreach (var pressedKey in pressedKeys)
            {
                this.OnKeyPressed(pressedKey, modifiers);
            }

            var releasedKeys = this.previousKeys.ToList();
            releasedKeys.RemoveAll(pressedKeys.Contains);

            foreach (var releasedKey in releasedKeys)
            {
                this.OnKeyReleased(releasedKey, modifiers);
            }

            this.previousKeys = keyboardState.GetPressedKeys().ToList();
        }

        private void OnKeyPressed(Keys key, IEnumerable<Keys> modifiers)
        {
            var args = new KeyboardArgs { Key = key, Modifiers = modifiers };

            if (this.KeyPressed != null)
            {
                this.KeyPressed(args);
            }
        }

        private void OnKeyReleased(Keys key, IEnumerable<Keys> modifiers)
        {
            var args = new KeyboardArgs { Key = key, Modifiers = modifiers };

            if (this.KeyReleased != null)
            {
                this.KeyReleased(args);
            }
        }
    }
}